Android Tips #45 Dialog をフルカスタマイズする
はじめに
以前より社内で Dialog のデザイン変えたりレイアウト変えたりいろいろカスタマイズしたい!という要件を耳にすることが多いのでフルカスタマイズする方法を書き留めておきたいと思います。今回は例として下図のようなレイアウトの Dialog を作ってみたいと思います。
DialogFragment をカスタマイズする
まず大前提として DialogFragment を継承したクラスでカスタマイズしましょう! Dialog を new して show するのはもう時代遅れです。Support Package を使えば Android 1.6 から使うことができますよ。
CustomDialogFragment.java
package jp.classmethod.android.sample.customdialog; import android.app.Dialog; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; public class CustomDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Dialog dialog = new Dialog(getActivity()); // タイトル非表示 dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); // フルスクリーン dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); dialog.setContentView(R.layout.dialog_custom); // 背景を透明にする dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // OK ボタンのリスナ dialog.findViewById(R.id.positive_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); // Close ボタンのリスナ dialog.findViewById(R.id.close_button).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); return dialog; } }
ポイントは3点、いずれも Dialog#getWindow() で Dialog が持っている Window インスタンスに対する設定です。
まず20行目の Window#requestFeature() でデフォルトのタイトルを消します。このメソッドは Dialog#setContentView() より先に呼ばなければいけないので注意してください。Window.FEATURE_NO_TITLE を渡すとタイトルが消えます。
次に22行目の Window#setFlags() で WindowManager.LayoutParams.FLAG_FULLSCREEN を渡し、 Dialog をフルスクリーン表示にします。
最後に Window#setBackgroundDrawable() でデフォルトテーマに付いている影などを消します。
これでデフォルトテーマをかき消して自分が作った View だけ表示されるようになります!あとは自由自在にできますね。 OK ボタンや Close ボタンはすべてカスタムレイアウトに定義されていることとし、好きな処理を書いていきます。
おまけ
要点は以上になりますが、おまけとして今回作ったカスタムのレイアウトを載せておきます。Drawable も全部 XML で書いてみました。デザインを実装に落としこむときの参考までに。
dialog_custom.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- コンテンツ --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_below="@+id/title" android:layout_marginTop="6dp" android:layout_marginLeft="6dp" android:layout_marginRight="6dp" android:paddingBottom="20dp" android:background="@drawable/bg_dialog" android:gravity="center_horizontal" android:orientation="vertical" > <!-- タイトル --> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_dialog_title" android:padding="10dp" android:text="Title" android:textSize="18sp" android:textColor="@android:color/white" /> <!-- メッセージ --> <TextView android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:lineSpacingExtra="6dp" android:text="MessageMessageMessageMessageMessageMessageMessageMessageMessage" android:textSize="16sp" android:textColor="#333333" /> <!-- OK ボタン --> <Button android:id="@+id/positive_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="6dp" android:background="@drawable/bt_dialog_positive" android:text="OK" android:textColor="@android:color/white" /> </LinearLayout> <!-- Close ボタン --> <Button android:id="@+id/close_button" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:background="@drawable/bt_dialog_close" android:text="×" android:textColor="#9acd32" /> </RelativeLayout>
bg_dialog.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <corners android:radius="5dp"/> <stroke android:width="2dp" android:color="#9acd32"/> <gradient android:startColor="#ffffff" android:endColor="#dcdcdc" android:angle="90"/> </shape>
背景は角丸矩形にグラデーションをほんわり付けてます。
bg_title.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <corners android:topLeftRadius="5dp" android:topRightRadius="5dp"/> <solid android:color="#9acd32"/> </shape>
タイトルの背景は右上と左上だけ角丸になるようにしています。
bt_dialog_positive.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <corners android:radius="5dp" /> <solid android:color="#9acd32" /> </shape>
OK ボタンは普通の角丸矩形です。本来であれば selector を使うところですが省略してます。
bt_dialog_close.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@android:color/white"/> <stroke android:width="3dp" android:color="#9acd32" /> </shape>
Close ボタンは android:shape="oval" にすることで円を書いています。"×" は直接テキストにしているので、端末のフォントによってはデザインが変わってしまいますね…。
まとめ
「Dialog をこんなデザインにしたいからよろしく!」と急にふられたときもこれで安心ですね!